interface Result {
  data?: {
    userInfo?: {
      name: string;
    };
  };
}

// type userInfo = Result['data']['userInfo'];

// 简单写法
type userInfo = Required<Required<Result>["data"]>["userInfo"];

/**
 * Required 是怎么实现的
 * type Required<T> = {[K in keyof T]-?:T[K]}
 * K in keyof T 就是遍历索引类型T中的所有索引K
 * 用来构造新的索引类型, 值保持不变,也就是T[K]不变
 * 可以看到Required<T>是一个类型，它的类型参数是T，它的键是K，值是T[K]，
 */

// 复杂写法
type IsOptional<Key extends keyof Obj, Obj> = {} extends Pick<Obj, Key>
  ? Key
  : never;
type DeepRequired<Obj> = Obj extends any
  ? {
      [Key in keyof Obj]-?: IsOptional<Key, Obj> extends never
        ? Obj[Key]
        : DeepRequired<Obj[Key]>;
    }
  : never;

type userInfo2 = DeepRequired<Result>["data"]["userInfo"];
